package cn.touna.jss.common.mybatis;

import cn.touna.jss.common.properties.config.DBProperties;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

@Configuration
// 扫描 Mapper 接口并容器管理
@MapperScan(basePackages = {"cn.touna.jss.modules.**.mapper"}, sqlSessionFactoryRef = "masterSqlSessionFactory")
public class DataSourceConfig implements EnvironmentAware {

    private static final Logger logger = LogManager.getLogger(DataSourceConfig.class);

    @Autowired
    private DBProperties dbProperties;

    private RelaxedPropertyResolver propertyResolver;

    @Bean(name = "masterDataSource")
    @Primary
    public DruidDataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        try {
            dataSource.setDriverClassName(dbProperties.getDriverClassName());
            dataSource.setUrl(dbProperties.getUrl());
            dataSource.setUsername(dbProperties.getUsername());
            dataSource.setPassword(dbProperties.getPassword());
            dataSource.setMaxActive(dbProperties.getMaxActive());
            dataSource.setMaxWait(dbProperties.getMaxWait());
            dataSource.setInitialSize(dbProperties.getInitialSize());
            dataSource.setMinIdle(dbProperties.getMinIdle());
            dataSource.setTimeBetweenEvictionRunsMillis(dbProperties.getTimeBetweenEvictionRunsMillis());
            dataSource.setMinEvictableIdleTimeMillis(dbProperties.getMinEvictableIdleTimeMillis());
            dataSource.setValidationQuery(dbProperties.getValidationQuery());
            dataSource.setTestWhileIdle(true);
            dataSource.setTestOnBorrow(false);
            dataSource.setTestOnReturn(false);
            dataSource.setFilters(dbProperties.getFilters());
            StatFilter statFilter = new StatFilter();
            statFilter.setSlowSqlMillis(5000);
            statFilter.setMergeSql(true);
        } catch (Exception e) {
            logger.error("PRO 【数据源配置】异常，异常信息msg:{}", e);
        }
        return dataSource;
    }

    @Bean(name = "masterSqlSessionFactory")
    @Primary
    public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DruidDataSource dataSource)
            throws Exception {
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setTypeAliasesPackage(propertyResolver.getProperty("typeAliasesPackage"));
        sessionFactory.setMapperLocations(resourcePatternResolver.getResources(propertyResolver.getProperty("mapper-locations")));
        sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(propertyResolver.getProperty("configLocation")));
        return sessionFactory.getObject();
    }

    @Bean(name = "masterTransactionManager")
    @Primary
    public DataSourceTransactionManager masterTransactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }


    @Override
    public void setEnvironment(Environment environment) {
        this.propertyResolver = new RelaxedPropertyResolver(environment, "mybatis.");
    }

}